GChanges = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0", "AceEvent-2.0", "AceDB-2.0", "AceDebug-2.0", "FuBarPlugin-2.0")
local dewdrop = AceLibrary("Dewdrop-2.0")
local tablet = AceLibrary("Tablet-2.0")
local L = AceLibrary("AceLocale-2.2"):new("GChanges")

GChanges:RegisterDB("GCDB", "GCDBPC")
GChanges:RegisterDefaults("profile", {
	["guilds"] = {},
	["dateformat"] = "%x",
	["show"] = {
		["new"] = false,
		["gone"] = false,
		["level"] = false,
		["rank"] = false,
		["note"] = false,
		["onote"] = false,
	}
})

local vars = {
	["version"] = " 0.5 ",
	["guild"] = "",
	["first"] = "",
	["last"] = "",
	["changes"] = {
		["new"] = {},
		["gone"] = {},
		["level"] = {},
		["rank"] = {},
		["note"] = {},
		["onote"] = {},
	}
}


GChanges.hasIcon = "Interface\\Icons\\INV_Scroll_03"

function GChanges:OnInitialize()
	--self:SetDebugging(true)	
	GChanges:RegisterChatCommand({"/gchanges"}, self.options)
	self:Debug("/commands loaded")
	self:Print(L["version"] .. vars.version ..L["loaded"])
	GuildRoster()
	vars.guild = GetGuildInfo("player")
end

function GChanges:Refresh()
	vars.guild = GetGuildInfo("player")
	if vars.guild == nil then
		self:Print(L["noCapture"])
	else
		self:Print(L["capture"])
	end
end

GChanges.clickableTooltip = true
function GChanges:OnMenuRequest(level, value)
	vars.guild = GetGuildInfo("player")
	if level == 1 then
		dewdrop:AddLine(
			'text', L["startingDate"],
			'value', "first",
			'hasArrow', true
		)
		dewdrop:AddLine(
			'text', L["endingDate"],
			'value', "last",
			'hasArrow', true
		)
		dewdrop:AddLine(
			'text', L["record"],
			'arg1', self,
			'func', "CheckGuild"
		)
		dewdrop:AddLine(
			'text', L["refresh"],
			'arg1', self,
			'func', "Refresh"
		)
		dewdrop:AddLine(
			'text', L["dateformatting"],
			'value', "datef",
			'hasArrow', true
		)
		dewdrop:AddLine(
			'text', L["delete"],
			'value', "delete",
			'hasArrow', true
		)
	elseif level == 2 then
		if value == "first" then
			if not (vars.guild == nil) then
				for d in self:Sorted(self.db.profile.guilds[vars.guild]) do
					if (vars.last == "") or (self:Order(d) < self:Order(vars.last)) then
						dewdrop:AddLine(
							'text', self:Format(d),
							'isRadio', true,
							'arg1', self,
							'arg2', d,
							'func', function()
								self:Debug("setting first to", d)
								vars.first = d
								self:Compare()
							end,
							'checked', self:IsChecked(d, "first")
						)
					end
				end
			else
				dewdrop:AddLine('text', L["err"])
			end
		elseif value == "last" then
			if not (vars.guild == nil) then
				for d in self:Sorted(self.db.profile.guilds[vars.guild]) do
					if (self:Order(d) > self:Order(vars.first)) then
						dewdrop:AddLine(
							'text', self:Format(d),
							'isRadio', true,
							'arg1', self,
							'arg2', d,
							'func', function()
								self:Debug("setting last to", d)
								vars.last = d
								self:Compare()
							end,
							'checked', self:IsChecked(d, "last")
						)
					end
				end
			else
				dewdrop:AddLine('text', L["err"])
			end
		elseif value == "delete" then
			dewdrop:AddLine(
				'text', L["deletebefore"],
				'value', "before",
				'hasArrow', true
			)
			dewdrop:AddLine(
				'text', L["deleteafter"],
				'value', "after",
				'hasArrow', true
			)
			dewdrop:AddLine(
				'text', L["deletesingle"],
				'value', "single",
				'hasArrow', true
			)
		elseif value == "datef" then
			dewdrop:AddLine(
				'text', L["dateonly"],
				'isRadio', true,
				'arg1', self,
				'func', function()
					self.db.profile.dateformat = "%x"
				end,
				'checked', (self.db.profile.dateformat)
			)
			dewdrop:AddLine(
				'text', L["datetime"],
				'isRadio', true,
				'arg1', self,
				'func', function()
					self.db.profile.dateformat = nil
				end,
				'checked', (not self.db.profile.dateformat)
			)
		end
	elseif level == 3 then
		if value == "before" then
			if not (vars.guild == nil) then
				dewdrop:AddLine('text', L["deletebefore"])
				for d in self:Sorted(self.db.profile.guilds[vars.guild]) do
					dewdrop:AddLine(
						'text', self:Format(d),
						'arg1', self,
						'arg2', d,
						'func', function()
							self:Debug("deleting all up to ", d)
							for k in self:Sorted(self.db.profile.guilds[vars.guild]) do
								self:Debug(k)
								if (k < d) then self:DeleteRecord(k) end
							end
						end,
						'checked', self:IsChecked(d, "last")
					)
				end
			else
				dewdrop:AddLine('text', L["err"])
			end
		elseif value == "after" then
			if not (vars.guild == nil) then
				dewdrop:AddLine('text', L["deleteafter"])
				for d in self:Sorted(self.db.profile.guilds[vars.guild]) do
					dewdrop:AddLine(
						'text', self:Format(d),
						'arg1', self,
						'arg2', d,
						'func', function()
							self:Debug("deleting all past ", d)
							for k in self:Sorted(self.db.profile.guilds[vars.guild]) do
								self:Debug(k)
								if (k > d) then self:DeleteRecord(k) end
							end
						end,
						'checked', self:IsChecked(d, "last")
					)
				end
			else
				dewdrop:AddLine('text', L["err"])
			end
		elseif value == "single" then
			if not (vars.guild == nil) then
				dewdrop:AddLine('text', L["deletesingle"])
				for d in self:Sorted(self.db.profile.guilds[vars.guild]) do
					dewdrop:AddLine(
						'text', self:Format(d),
						'arg1', self,
						'arg2', d,
						'func', function()
							self:Debug("deleting ", d)
							self:DeleteRecord(d)
						end,
						'checked', self:IsChecked(d, "last")
					)
				end
			else
				dewdrop:AddLine('text', L["err"])
			end
		end
	end	
end


function GChanges:OnTooltipUpdate()
	local cat = tablet:AddCategory(
		'columns', 3
	)
	for rawr in pairs(vars.changes.new) do
		cat:AddLine(
			'text', L["newMembers"], 
			'textR', 1, 'textG', 1, 'textB', 1,
			'checked', true, 'hasCheck', true, 
			'checkIcon', self.db.profile.show.new and "Interface\\Buttons\\UI-MinusButton-Up" or "Interface\\Buttons\\UI-PlusButton-Up",
			'func', function()
				self.db.profile.show.new = not self.db.profile.show.new
			end
		)
		if self.db.profile.show.new then
			for k in pairs(vars.changes.new) do
				cat:AddLine(
					'text', k
				)
			end
		end
		break
	end
	for rawr in pairs(vars.changes.gone) do
		cat:AddLine(
			'text', L["formerMembers"], 
			'textR', 1, 'textG', 1, 'textB', 1,
			'checked', true, 'hasCheck', true, 
			'checkIcon', self.db.profile.show.gone and "Interface\\Buttons\\UI-MinusButton-Up" or "Interface\\Buttons\\UI-PlusButton-Up",
			'func', function()
				self.db.profile.show.gone = not self.db.profile.show.gone
			end
		)
		if self.db.profile.show.gone then
			for k in pairs(vars.changes.gone) do
				cat:AddLine(
					'text', k
				)
			end
		end
		break
	end
	for rawr in pairs(vars.changes.level) do
		cat:AddLine(
			'text', L["levelChange"], 
			'text2', L["oldLevel"] .. " - " .. L["newLevel"], 
			'textR', 1, 'textG', 1, 'textB', 1,
			'text2R', 1, 'text2G', 1, 'text2B', 1,
			'checked', true, 'hasCheck', true, 
			'checkIcon', self.db.profile.show.level and "Interface\\Buttons\\UI-MinusButton-Up" or "Interface\\Buttons\\UI-PlusButton-Up",
			'func', function()
				self.db.profile.show.level = not self.db.profile.show.level
			end
		)
		if self.db.profile.show.level then
			for k in pairs(vars.changes.level) do
				cat:AddLine(
					'text', k,
					'text2', vars.changes.level[k].old .. " - " .. vars.changes.level[k].new
				)
			end
		end
		break
	end
	for rawr in pairs(vars.changes.rank) do
		cat:AddLine(
			'text', L["rankChange"], 
			'text2', L["oldRank"], 
			'text3', L["newRank"], 
			'textR', 1, 'textG', 1, 'textB', 1,
			'text2R', 1, 'text2G', 1, 'text2B', 1,
			'text3R', 1, 'text3G', 1, 'text3B', 1,
			'checked', true, 'hasCheck', true, 
			'checkIcon', self.db.profile.show.rank and "Interface\\Buttons\\UI-MinusButton-Up" or "Interface\\Buttons\\UI-PlusButton-Up",
			'func', function()
				self.db.profile.show.rank = not self.db.profile.show.rank
			end
		)
		if self.db.profile.show.rank then
			for k in pairs(vars.changes.rank) do
				cat:AddLine(
					'text', k,
					'text2', vars.changes.rank[k].old,
					'text3', vars.changes.rank[k].new
				)
			end
		end
		break
	end
	for rawr in pairs(vars.changes.note) do
		cat:AddLine(
			'text', L["noteChange"], 
			'text2', L["oldNote"], 
			'text3', L["newNote"], 
			'textR', 1, 'textG', 1, 'textB', 1,
			'text2R', 1, 'text2G', 1, 'text2B', 1,
			'text3R', 1, 'text3G', 1, 'text3B', 1,
			'checked', true, 'hasCheck', true, 
			'checkIcon', self.db.profile.show.note and "Interface\\Buttons\\UI-MinusButton-Up" or "Interface\\Buttons\\UI-PlusButton-Up",
			'func', function()
				self.db.profile.show.note = not self.db.profile.show.note
			end
		)
		if self.db.profile.show.note then
			for k in pairs(vars.changes.note) do
				cat:AddLine(
					'text', k,
					'text2', vars.changes.note[k].old,
					'text3', vars.changes.note[k].new
				)
			end
		end
		break
	end
	for rawr in pairs(vars.changes.onote) do
		cat:AddLine(
			'text', L["onoteChange"], 
			'text2', L["oldNote"], 
			'text3', L["newNote"], 
			'textR', 1, 'textG', 1, 'textB', 1,
			'text2R', 1, 'text2G', 1, 'text2B', 1,
			'text3R', 1, 'text3G', 1, 'text3B', 1,
			'checked', true, 'hasCheck', true, 
			'checkIcon', self.db.profile.show.onote and "Interface\\Buttons\\UI-MinusButton-Up" or "Interface\\Buttons\\UI-PlusButton-Up",
			'func', function()
				self.db.profile.show.onote = not self.db.profile.show.onote
			end
		)
		if self.db.profile.show.onote then
			for k in pairs(vars.changes.onote) do
				cat:AddLine(
					'text', k,
					'text2', vars.changes.onote[k].old,
					'text3', vars.changes.onote[k].new
				)
			end
		end
		break
	end
end

function GChanges:OnEnable()
	self:Debug("OnEnable()")
	vars.guild = GetGuildInfo("player")
end

function GChanges:OnDisable()
	
end

function GChanges:CheckGuild()
	if not vars.guild then vars.guild = GetGuildInfo("player") end
	self:Debug("Starting Guild Check")
	local name, rank, level, note, officernote
	local timestamp = date()
	self:Debug("Name:", vars.guild, "Time:", timestamp)
	
	if not self.db.profile.guilds[vars.guild] then
		self:Debug("Guild name not in database yet")
		self.db.profile.guilds[vars.guild] = {}
	end
	if not self.db.profile.guilds[vars.guild][timestamp] then
		self:Debug("Timestamp not in database yet")
		self.db.profile.guilds[vars.guild][timestamp] = {}
	end
	
	self:Debug("Starting Member count", GetNumGuildMembers(true))
	for i=1, GetNumGuildMembers(true) do
		name, rank,_, level, class,_, note, officernote = GetGuildRosterInfo(i)
		self:Debug(i, name, rank, level, note, officernote)
		if not self.db.profile.guilds[vars.guild][timestamp][name] then
			self:Debug("Not added yet")
			self.db.profile.guilds[vars.guild][timestamp][name] = {
				["class"] = nil,
				["rank"] = nil,
				["level"] = nil,
				["note"] = nil,
				["onote"] = nil,
			}
		end
		self.db.profile.guilds[vars.guild][timestamp][name] = {
			["class"] = string.upper(class),
			["rank"] = rank,
			["level"] = level,
			["note"] = note,
			["onote"] = officernote,
		}
		self:Debug(name, "added to guild", vars.guild, "on date", timestamp)
	end
	self:Debug("Done adding members")
	self:Debug("Adding MOTD")
	self.db.profile.guilds[vars.guild][timestamp].motd = GetGuildRosterMOTD()
end

function GChanges:Compare()
	vars.changes = {
		["new"] = {},
		["gone"] = {},
		["level"] = {},
		["rank"] = {},
		["note"] = {},
		["onote"] = {},
	}
	if not vars.guild then vars.guild = GetGuildInfo("player") end
	
	self:Debug(vars.first, vars.last)
	self:Debug("Checking that records exist")
	if not self.db.profile.guilds[vars.guild][vars.first] then self:Debug("Error:  No record found for " .. vars.first) return end
	if not self.db.profile.guilds[vars.guild][vars.last] then self:Debug("Error:  No record found for " .. vars.last) return end
	self:Debug("Records do exist")
	self:Debug("Starting first loop for new people and new info")
	for name in pairs(self.db.profile.guilds[vars.guild][vars.last]) do
		--self:Debug(name)
		if not self.db.profile.guilds[vars.guild][vars.first][name] then
			self:Debug("new")
			----self:Print(name .. " is new to the guild")
			vars.changes.new[self:NameColor(name, self.db.profile.guilds[vars.guild][vars.last][name].class)] = true
		else
			--self:Debug("not new")
			--self:Debug("level", self.db.profile.guilds[vars.guild][vars.first][name]["level"], self.db.profile.guilds[vars.guild][vars.last][name]["level"])
			--self:Debug("onote", self.db.profile.guilds[vars.guild][vars.first][name]["onote"], self.db.profile.guilds[vars.guild][vars.last][name]["onote"])
			--self:Debug("note", self.db.profile.guilds[vars.guild][vars.first][name]["note"], self.db.profile.guilds[vars.guild][vars.last][name]["note"])
			--self:Debug("rank", self.db.profile.guilds[vars.guild][vars.first][name]["rank"], self.db.profile.guilds[vars.guild][vars.last][name]["rank"])
			if not (self.db.profile.guilds[vars.guild][vars.first][name]["level"] == self.db.profile.guilds[vars.guild][vars.last][name]["level"]) then
				--self:Print(name .. " has gone from level " .. self.db.profile.guilds[vars.guild][vars.first][name]["level"] .. " to level " .. self.db.profile.guilds[vars.guild][vars.last][name]["level"])
				vars.changes.level[self:NameColor(name, self.db.profile.guilds[vars.guild][vars.last][name].class)] = {
					["old"] = self.db.profile.guilds[vars.guild][vars.first][name].level,
					["new"] = self.db.profile.guilds[vars.guild][vars.last][name].level
				}
			end
			if not (self.db.profile.guilds[vars.guild][vars.first][name]["rank"] == self.db.profile.guilds[vars.guild][vars.last][name]["rank"]) then
				--self:Print(name .. " has gone from rank " .. self.db.profile.guilds[vars.guild][vars.first][name]["rank"] .. " to rank " .. self.db.profile.guilds[vars.guild][vars.last][name]["rank"])
				vars.changes.rank[self:NameColor(name, self.db.profile.guilds[vars.guild][vars.last][name].class)] = {
					["old"] = self.db.profile.guilds[vars.guild][vars.first][name].rank,
					["new"] = self.db.profile.guilds[vars.guild][vars.last][name].rank
				}
			end
			if not (self.db.profile.guilds[vars.guild][vars.first][name]["note"] == self.db.profile.guilds[vars.guild][vars.last][name]["note"]) then
				--self:Print(name .. "'s note has changed from \"" .. self.db.profile.guilds[vars.guild][vars.first][name]["note"] .. "\" to \"" .. self.db.profile.guilds[vars.guild][vars.last][name]["note"].."\"")
				vars.changes.note[self:NameColor(name, self.db.profile.guilds[vars.guild][vars.last][name].class)] = {
					["old"] = self.db.profile.guilds[vars.guild][vars.first][name].note,
					["new"] = self.db.profile.guilds[vars.guild][vars.last][name].note
				}
			end
			if not (self.db.profile.guilds[vars.guild][vars.first][name]["onote"] == self.db.profile.guilds[vars.guild][vars.last][name]["onote"]) then
				--self:Print(name .. "'s officer note has changed from \"" .. self.db.profile.guilds[vars.guild][vars.first][name]["onote"] .. "\" to \"" .. self.db.profile.guilds[vars.guild][vars.last][name]["onote"].."\"")
				vars.changes.onote[self:NameColor(name, self.db.profile.guilds[vars.guild][vars.last][name].class)] = {
					["old"] = self.db.profile.guilds[vars.guild][vars.first][name].onote,
					["new"] = self.db.profile.guilds[vars.guild][vars.last][name].onote
				}
			end
		end
	end
	self:Debug("first loop done")
	self:Debug("starting second loop for gone people")
	for name in pairs(self.db.profile.guilds[vars.guild][vars.first]) do
		--self:Debug(name)
		if not self.db.profile.guilds[vars.guild][vars.last][name] then
			--self:Debug("new")
			--self:Print(name .. " has left the guild")
			vars.changes.gone[self:NameColor(name, self.db.profile.guilds[vars.guild][vars.first][name].class)] = true
		end
	end
end

function GChanges:IsChecked(d, s)
	return (d == vars[s])
end

function GChanges:Sorted(t, f)
	local a = {}
	for n in pairs(t) do table.insert(a, n) end
	if not f then f = function(a,b) return GChanges:Order(a) < GChanges:Order(b) end end
	table.sort(a, f)
	local i = 0      -- iterator variable
	local iter = function ()   -- iterator function
		i = i + 1
		if a[i] == nil then return nil
		else return a[i], t[a[i]]
		end
	end
	return iter
end

function GChanges:Bug()
	self:Order("12/26/06")
	self:Order("12/26/06 21:45:24")
end

function GChanges:DeleteRecord(d)
	if not (self.db.profile.guilds[vars.guild][d] == nil) then
		self:Print(d.." "..L["del"])
		self.db.profile.guilds[vars.guild][d] = nil
	end
end

function GChanges:ParseDate(d)
	local t = {}
	for k in d:gmatch("%d+") do
		--self:Print(k)
		table.insert(t, k)
	end	
	return t

end

function GChanges:Order(d)
	local t = self:ParseDate(d)
	local str
	local da, mo, y, h, mi, s = t[2], t[1], t[3], t[4], t[5], t[6]
	if not da then
		str = "0 0 0 0 0 0"
	elseif not h then
		str = y.." "..mo.." "..da.." 0 0 0"
	else
		str = y.." "..mo.." "..da.." "..h.." "..mi.." "..s
	end
	--self:Print(str)
	return str
end
	
function GChanges:Format(d)
	local t = self:ParseDate(d)
	local str
	local da, mo, y, h, mi, s = t[2], t[1], t[3], t[4], t[5], t[6]
	if not da then
		str = "0 0 0 0 0 0"
	elseif self.db.profile.dateformat == "%x" then
		str = mo.."/"..da.."/"..y
	else
		str = mo.."/"..da.."/"..y.." "..(h or 0)..":"..(mi or 0)..":"..(s or 0)
	end
	return str
end

function GChanges:NameColor(name, class)
	if not class then
		return name
	end
	local color = string.format("|cff%02x%02x%02x", (RAID_CLASS_COLORS[class].r*255), (RAID_CLASS_COLORS[class].g*255), (RAID_CLASS_COLORS[class].b*255)) 
	return (color .. name)
end
